Gradle with CI
ビルドはローカルでの開発だけでなくテストや成果物の生成などを別のCIサーバなどで行うこともある。
考慮すべき点
どの gradle で実行するか
ほかのビルドと共有できる資源は何か
gradle daemon プロセスは共有できるかどうか
Gradle のいろいろなキャッシュができるかどうか
何をキャッシュするか
どのようにキャッシュを共有するか
どのような単位でキャッシュをするか
並列実行の方法
ビルド・テスト結果の参照方法
各環境についてはそれぞれのページを参照
Gradle with Jenkins
Gradle with GitHub Actions
Gradle with CircleCI
Gradle with drone.io
Gradle with TeamCity
以下、共通した話題について。
どの gradle で実行するか
基本的には以下のいずれかとなる。
CI の実行サーバにインストールされている gradle
プロジェクトに追加されている gradle wrapper
前者の場合は、ホストマシン自体に gradle をインストールしている場合や、gradle を同梱したコンテナイメージを利用するなどがある。
トレードオフ
実行前のコスト <-> 実行時のコスト
CI サービス自体の運用コスト
ネットワークコストとストレージコスト
事前インストールされているためビルド時の初期化処理としてインストール作業を行う必要がない
実行時に gradle wrapper の distribution file を準備する時間を必要とする。
CI側で gradle 特有の準備をする必要がない
プロジェクト側で準備する必要がある
gradle wrapper の distribution file ダウンロード回数や通信量
drone.io や CircleCI などはデフォルトで docker サービスを利用することができ、公式が用意している gradle イメージを利用することで同時にいろいろな問題を解決できる場合がある。欠点としては最新バージョンの反映が若干遅めのため常に最新を使いたい場合などに影響がある場合がある。
ほかのビルドと共有できる資源は何か
基本的には前回のビルドの結果を再利用する。
「前回」の定義は若干種類があり、ビルド対象のプロジェクトのコードが変更される前を前回とする場合や、一回のビルドを分割し複数の段階がある場合の前の段階のビルドであったりする。
CIホストマシン上で直接実行できる場合はローカルでの開発のようにほぼすべての資源を利用することができる
コンテナサーバで実行するパターンでは workspace を mount して共有したり、外部のオブジェクトストレージに格納したりできる場合がある。オブジェクトストレージの場合でも対象キーの上書きができるかどうかによってもCIのキャッシュキーが若干変わる。
ほとんどの CI サービスのドキュメントでは GRADLE_USER_HOME の caches ディレクトリをまるごとキャッシュしているが、この場合数GBにも及ぶ場合があるため オブジェクトストレージやネットワークの金額が膨大になったり、ビルドそのものに関してもダウンロード時間が長くなり、結果としてビルド時間が長くなる場合もある。
ちなみに公式で提供されている GitHub Actions の gradle-build-action を参考に、キャッシュ可能なファイルを確認すると以下のものがある。他のCIでも 同じようにキャッシュすると良いかもしれないがキャッシュキーが結構複雑なためそのまま反映するのはなかなか難しい。
GRADLE_USER_HOME
caches
notifications
(jdk)
project ごとの .gradle
configuration-cache
jenkins の場合は完全に運用によるが、ホストと同じサーバである場合ほとんどの資源を共有できる。ただし、並列実行は dependency cache は複数の gradle 実行から書き込みを行おうとすると lock があるため問題がある場合がある。
drone.io は そのCIサービス自体には特にサポートはないが plugin として 外部のオブジェクトストレージに保存、取得することでキャッシュを共有できる。
CircleCI や GitHub Actions はCIサービスとしてキャッシュをサポートしている。
どの場合においても Build Cache の remote host を使うことは可能ではある。うまく動かせた例がないので割愛。
ビルド・テスト結果の参照方法
JUnit 形式の xml を出力する場合、CIサービス自身がその xml を解釈してまとめてくれる場合もある。
そうでない場合も html 形式の出力結果をオブジェクトストレージなどに格納することで整理された結果を見られる。
https://docs.gradle.org/current/userguide/dependency_resolution.html#sub:ephemeral-ci-cache